package cn.magictodo.weblog.common.domain.mapper;


import cn.magictodo.weblog.common.domain.dos.ArticleDO;
import cn.magictodo.weblog.common.domain.dos.ArticlePublishCountDO;
import cn.magictodo.weblog.common.domain.vos.ArticleCategoryNameVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.time.LocalDate;
import java.util.List;
import java.util.Objects;

/**
 * ArticleMapper 文章接口
 *
 * @author liu
 * @since 2023-11-24 20:55
 */
@Mapper
public interface ArticleMapper extends BaseMapper<ArticleDO> {

    /**
     * 分页联表查询.后台文章管理使用
     * @param current 当前页码
     * @param size 每页展示的数据量
     * @param title 文章标题
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return
     */
    default Page<ArticleCategoryNameVO> selectPageList(Long current, Long size, String categoryName, String title, LocalDate startDate, LocalDate endDate, Boolean isPublish,Integer isTop,Integer type) {
        // 分页对象(查询第几页、每页多少数据)
        Page<ArticleCategoryNameVO> page = new Page<>(current, size);

        if (StringUtils.isNotBlank(title)){title=title.trim();}
//        手动关闭 SQL 优化，不然查询总数的时候只会查询主表
        page.setOptimizeCountSql(false);



        QueryWrapper<ArticleCategoryNameVO> objectQueryWrapper = new QueryWrapper<>();
        // 构建查询条件
        objectQueryWrapper
                .like(StringUtils.isNotBlank(title), "title", title) // like 模块查询
                .ge(Objects.nonNull(startDate),"create_time", startDate) // 大于等于 startDate
                .le(Objects.nonNull(endDate), "create_time", endDate)  // 小于等于 endDate
                .eq(Objects.nonNull(isPublish), "is_publish", isPublish) // 是否推送
                .ge(Objects.nonNull(isTop)&&(isTop!=0),"weight", isTop)
                .eq(Objects.nonNull(isTop)&&(isTop==0),"weight", isTop)
                .like(StringUtils.isNotBlank(categoryName), "tc.name", categoryName) // like 模块查询
                .eq(Objects.nonNull(type), "type", type)
                .orderByDesc("weight")
                .orderByDesc("create_time"); // 按创建时间倒叙

        return selectArticleVCategoryNameList(page, objectQueryWrapper);
    }


    /**
     * 分页查询*前台首页
     * @param current 当前页码
     * @param size 每页展示的数据量
     * @param type 文章类型
     * @return
     */
    default Page<ArticleDO> selectPageList(Long current, Long size,Integer type) {
        // 分页对象(查询第几页、每页多少数据)
        Page<ArticleDO> page = new Page<>(current, size);

        // 构建查询条件
        LambdaQueryWrapper<ArticleDO> wrapper = Wrappers.<ArticleDO>lambdaQuery()
                .eq(ArticleDO::getIsPublish, true) // 是否推送
                .eq(type!=null, ArticleDO::getType, type)// 文章类型
                .orderByDesc(ArticleDO::getWeight)// 按权重倒叙
                .orderByDesc(ArticleDO::getCreateTime); // 按创建时间倒叙



        return selectPage(page, wrapper);
    }


    /**
     * 分页查询*前台归档
     * @param size 当前页展示数量
     * @return
     */
    default Page<ArticleDO> selectPageList(Long size) {
        // 分页对象(查询第几页、每页多少数据)
        Page<ArticleDO> page = new Page<>(1, size);

        // 构建查询条件
        LambdaQueryWrapper<ArticleDO> wrapper = Wrappers.<ArticleDO>lambdaQuery()
                .eq( ArticleDO::getIsPublish, true) // 是否推送
                .orderByDesc(ArticleDO::getCreateTime); // 按创建时间倒叙

        return selectPage(page, wrapper);
    }

    /**
     * 根据文章 ID 批量分页查询*前台
     * @param current
     * @param size
     * @param articleIds
     * @return
     */
    default Page<ArticleDO> selectPageListByArticleIds(Long current, Long size, List<Long> articleIds) {
        // 分页对象(查询第几页、每页多少数据)
        Page<ArticleDO> page = new Page<>(current, size);

        // 构建查询条件
        LambdaQueryWrapper<ArticleDO> wrapper = Wrappers.<ArticleDO>lambdaQuery()
                .in(ArticleDO::getId, articleIds) // 批量查询
                .eq(ArticleDO::getIsPublish, true) // 已发布的文章
                .orderByDesc(ArticleDO::getWeight)
                .orderByDesc(ArticleDO::getCreateTime); // 按创建时间倒叙

        return selectPage(page, wrapper);
    }

    /**
     * 查询上一篇文章
     * @param articleId
     * @return
     */
    default ArticleDO selectPreArticle(Long articleId) {
        return selectOne(Wrappers.<ArticleDO>lambdaQuery()
                .orderByAsc(ArticleDO::getId) // 按文章 ID 升序排列
                .gt(ArticleDO::getId, articleId) // 查询比当前文章 ID 大的
                .eq(ArticleDO::getIsPublish, true) // 已发布的文章
                .last("limit 1")); // 第一条记录即为上一篇文章
    }

    /**
     * 查询下一篇文章
     * @param articleId
     * @return
     */
    default ArticleDO selectNextArticle(Long articleId) {
        return selectOne(Wrappers.<ArticleDO>lambdaQuery()
                .orderByDesc(ArticleDO::getId) // 按文章 ID 倒序排列
                .lt(ArticleDO::getId, articleId) // 查询比当前文章 ID 小的
                .eq(ArticleDO::getIsPublish, true) // 已发布的文章
                .last("limit 1")); // 第一条记录即为下一篇文章
    }

    /**
     * 阅读量+1
     * @param articleId
     * @return
     */
    default int increaseReadNum(Long articleId) {
        // 执行 SQL : UPDATE t_article SET read_num = read_num + 1 WHERE (id = XX)
        return update(null, Wrappers.<ArticleDO>lambdaUpdate()
                .setSql("read_num = read_num + 1")
                .eq(ArticleDO::getId, articleId));
    }

    /**
     * 查询所有记录的阅读量
     * @return
     */
    default List<ArticleDO> selectAllReadNum() {
        // 设置仅查询 read_num 字段
        return selectList(Wrappers.<ArticleDO>lambdaQuery()
                .select(ArticleDO::getReadNum));
    }

    /**
     * 按日分组，并统计每日发布的文章数量
     * @param startDate
     * @param endDate
     * @return
     */
    @Select("SELECT DATE(create_time) AS date, COUNT(*) AS count\n" +
            "FROM t_article\n" +
            "WHERE create_time >= #{startDate} AND create_time < #{endDate}  AND is_publish = true\n" +
            "GROUP BY DATE(create_time)")
    List<ArticlePublishCountDO> selectDateArticlePublishCount(LocalDate startDate, LocalDate endDate);


    Page<ArticleCategoryNameVO>  selectArticleVCategoryNameList(Page<ArticleCategoryNameVO> page,@Param(Constants.WRAPPER) QueryWrapper<ArticleCategoryNameVO> wrapper);

    /**
     * 查询最大权重值记录
     * @return
     */
    default ArticleDO selectMaxWeight() {
        return selectOne(Wrappers.<ArticleDO>lambdaQuery()
                .orderByDesc(ArticleDO::getWeight) // 按权重值降序排列
                .last("LIMIT 1")); // 仅查询出一条
    }

    /**
     * 批量更新文章
     * @param articleDO
     * @param ids
     * @return
     */
    default int updateByIds(ArticleDO articleDO, List<Long> ids) {
        return update(articleDO, Wrappers.<ArticleDO>lambdaUpdate()
                .in(ArticleDO::getId, ids));
    }

}